package br.com.virtual.base.controller.vender;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpSession;

import br.com.virtual.base.controller.carrinho.CarrinhoMB;
import br.com.virtual.base.controller.util.VirtualMB;
import br.com.virtual.base.enums.StatusVendaEnum;
import br.com.virtual.base.enums.TipoEnderecoEnum;
import br.com.virtual.base.enums.TipoPessoaEnum;
import br.com.virtual.base.exceptions.VirtualValidationException;
import br.com.virtual.base.service.SenderEmail;
import br.com.virtual.base.uteis.EnderecoDataModel;
import br.com.virtual.base.uteis.FileManager;
import br.com.virtual.cadastrar.model.Endereco;
import br.com.virtual.cadastrar.model.Pessoa;
import br.com.virtual.cadastrar.model.Usuario;
import br.com.virtual.cadastrar.service.EnderecoService;
import br.com.virtual.cadastrar.service.PessoaFisicaService;
import br.com.virtual.cadastrar.service.PessoaJuridicaService;
import br.com.virtual.correio.enums.TipoFrete;
import br.com.virtual.correio.service.CalculadorDeFreteService;
import br.com.virtual.vender.model.Frete;
import br.com.virtual.vender.model.ItemVenda;
import br.com.virtual.vender.model.Pagamento;
import br.com.virtual.vender.model.Venda;
import br.com.virtual.vender.service.PagamentoService;
import br.com.virtual.vender.service.VendaService;

@ManagedBean
@ViewScoped
public class VenderMB extends VirtualMB {

	
	private static final long serialVersionUID = 1L;
	
	
	private Pessoa cliente;
//	private Endereco endereco;
	private boolean renderFormVender = false;
	private Venda venda;
	private int maxParcela = 12;
	private int numeroParcelas;
	List<SelectItem> listOpPagamento;
	// List<Integer> listOpPagamento;
//	private boolean novoEndereco = false;
	private EnderecoDataModel enderecoDataModel;
	
	
	private TipoFrete tipoFrete;
	private Frete frete;
	
	@EJB private CalculadorDeFreteService calculadorDeFreteService;
	@EJB private EnderecoService enderecoService;
	@EJB private PagamentoService pagamentoService;
	@EJB private PessoaFisicaService pessoaFisicaService;
	@EJB private PessoaJuridicaService pessoaJuridicaService;
	@EJB private SenderEmail senderEmail;
	@EJB private VendaService vendaService;
	
	
	
	@ManagedProperty(value = "#{carrinhoMB}")
	private CarrinhoMB carrinhoMB;
	
	

	@PostConstruct
	private void init() {

		
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(true);

		venda = (Venda) session.getAttribute("carrinho");
		TipoFrete tf = (TipoFrete) session.getAttribute("tipoFrete");
		
//		this.venda = this.vendaService.read(32L);
//		this.venda.setItens(this.vendaService.getItens(venda));
		
		
		if(tf != null)
			tipoFrete = tf;
		else if( tipoFrete == null )
			 setTipoFrete( TipoFrete.PAC );
		
		Usuario usuario = (Usuario) session.getAttribute(Usuario.class
				.toString());
		cliente = usuario.getPessoa();

		this.carregarCliente();
		this.carregarEnderecoPrincipal();
		this.calculaFrete(venda.getItens(), venda.getEnderecoEntrega().getCep(), tipoFrete);
//		this.novo();
		
		
		
	}
	
	public void recalculaFrete(){
		this.calculaFrete(venda.getItens(), venda.getEnderecoEntrega().getCep(), tipoFrete);
	}
	
	private void calculaFrete(List<ItemVenda> produtos, String cepDestino, TipoFrete tipoFrete){
		
		if( cepDestino != null && !cepDestino.isEmpty() && tipoFrete != null){
			frete = calculadorDeFreteService.calculaPrecoPrazo(produtos, tipoFrete, CEP_ORIGEM, cepDestino);

//			venda.setValorFrete(frete.getValor());
			venda.setTotalFrete(frete.getValor().doubleValue());
			
			Calendar data = Calendar.getInstance();
			data.add(Calendar.DAY_OF_YEAR, frete.getPrazoEntrega());
			venda.setDataEntrega(data);
			
			venda.calculaTotal();
		}
	}

	private void carregarCliente() {
		if (cliente.getTipoPessoa().equals(TipoPessoaEnum.FISICA))
			cliente = this.pessoaFisicaService.carregar(cliente.getId());
		else
			cliente = this.pessoaJuridicaService.carregar(cliente.getId());
	}
	
	private void carregarEnderecoPrincipal(){
		
		if( venda.getEnderecoEntrega() == null || venda.getEnderecoEntrega().getId() == null ){
			Endereco enderecoEntrega = enderecoService.getEnderecoByTipo( cliente, TipoEnderecoEnum.PRINCIPAL);
			getVenda().setEnderecoEntrega(enderecoEntrega);
		}
	}
	
	public String doAlterarEnderecoEntrega(){
		
		return "/vender/selecionar-endereco.jsf?faces-redirect=true";
	}
	
	public String alterarEnderecoEntrega(Endereco enderecoSelecionado){

		venda.setEnderecoEntrega(enderecoSelecionado);
		return "/vender/finalizarcompra.jsf?faces-redirect=true";
	}
	
	public String novoEnderecoEntrega(){
	
		setSession("paginaRetorno", "/vender/selecionar-endereco.jsf?faces-redirect=true");
		return "/area_usuario/enderecos.jsf?faces-redirect=true";
	}

//	private void novo() {
//		this.novoEndereco = false;
//		endereco = new Endereco();
//		this.endereco.setTipoEndereco(TipoEndereco.ENTREGA);
//		this.enderecoDataModel = null;
//	}

	public String concluirVenda() {

		
		 
		venda.setCliente(cliente);
		venda.setDataVenda(Calendar.getInstance());
		venda.setDataEntrega(Calendar.getInstance());
		// venda.setEnderecoEntrega(new Endereco());
		// venda.setPagamento(pagamento);
		venda.setStatus(StatusVendaEnum.AGUARDANDO_PAGAMENTO);

		try {

			venda = vendaService.create(venda);
			Pagamento pagamento = pagamentoService.gerarPagamento(venda);
			
			this.senderEmail.sendVendaNotification(cliente.getEmail(), cliente.getNome(), 
					venda.getId().toString(), pagamento.getLinkPagamento(), venda.getStatus());
			
			new FileManager(CAMINHO_RETORNO).criarArquivo(venda.getId().toString());
			this.setFlash(Venda.class.getName(), venda);
			
			
			carrinhoMB.resetCarrinho();
//			addMessage("Compra concluída com sucesso.",
//					FacesMessage.SEVERITY_INFO);
			
			
			return "/vender/finalizado.jsf";

		} catch (VirtualValidationException e) {

			for (String err : e.getErros()) {

				this.addMessage(err, FacesMessage.SEVERITY_ERROR);
			}
		}

		return null;
	}

	private void addMessage(String message, FacesMessage.Severity severity) {

		FacesContext.getCurrentInstance().addMessage(null,
				new FacesMessage(severity, message, ""));

	}

	public String strTotalItens() {

		String str = "Total (%d %s):";
		int total = 0;

		for (ItemVenda i : venda.getItens()) {
			total += i.getQuantidade();
			maxParcela = (i.getProduto().getNumero_parcelas() > 0 && i
					.getProduto().getNumero_parcelas() < maxParcela) ? i
					.getProduto().getNumero_parcelas() : maxParcela;
		}

		return String.format(str, total, total == 1 ? "item" : "itens");
	}

	public List<SelectItem> opcoesPagamento() {

		listOpPagamento = new ArrayList<SelectItem>();
		StringBuilder textoParcela;
		
		this.venda.calculaTotal();
		
		for (int i = 1; i <= maxParcela; i++) {
			
//			BigDecimal totalParcela = this.venda.getTotalGeral().divide(new BigDecimal(i));
			Double totalParcela = this.venda.getTotalGeral() / i;
			
			textoParcela = new StringBuilder();
			textoParcela.append( i + " x de: ");
			textoParcela.append(NumberFormat.getCurrencyInstance().format(totalParcela));
			
			listOpPagamento.add(new SelectItem(i, textoParcela.toString()));
		}
		return listOpPagamento;
	}

	// public List<Integer> opcoesPagamento() {
	//
	// listOpPagamento = new ArrayList<Integer>();
	//
	// for (int i = 1; i <= maxParcela; i++) {
	// listOpPagamento.add(i);
	// }
	// return listOpPagamento;
	// }

//	public void adicionarEndereco() {
//
//		try {
//
//			this.endereco.setPessoa(this.cliente);
//			this.enderecoService.create(endereco);
//			this.venda.setEnderecoEntrega(endereco);
//
//			this.carregarCliente();
//			this.novo();
//		} catch (Exception e) {
//
//		}
//	}

	/*
	 * GETTERS AND SETTERS
	 */
	public Pessoa getCliente() {
		return cliente;
	}

	public void setCliente(Pessoa cliente) {
		this.cliente = cliente;
	}

	public Venda getVenda() {
		return venda;
	}

	public void setVenda(Venda venda) {
		this.venda = venda;
	}

	public int getMaxParcela() {
		return maxParcela;
	}

	public void setMaxParcela(int maxParcela) {
		this.maxParcela = maxParcela;
	}

	public int getNumeroParcelas() {
		return numeroParcelas;
	}

	public void setNumeroParcelas(int numeroParcelas) {
		this.numeroParcelas = numeroParcelas;
	}

	public List<SelectItem> getListOpPagamento() {
		if (listOpPagamento == null)
			listOpPagamento = opcoesPagamento();
		return listOpPagamento;
	}

	public void setListOpPagamento(List<SelectItem> listOpPagamento) {
		this.listOpPagamento = listOpPagamento;
	}

	public boolean isRenderFormVender() {

		renderFormVender = ((cliente.getId() == null) ? false : true);
		return renderFormVender;
	}

	public void setRenderFormVender(boolean renderFormVender) {
		this.renderFormVender = renderFormVender;
	}

	public CarrinhoMB getCarrinhoMB() {
		return carrinhoMB;
	}

	public void setCarrinhoMB(CarrinhoMB carrinhoMB) {
		this.carrinhoMB = carrinhoMB;
	}

//	public boolean isNovoEndereco() {
//		return novoEndereco;
//	}
//
//	public void setNovoEndereco(boolean novoEndereco) {
//		this.novoEndereco = novoEndereco;
//	}
//
//	public Endereco getEndereco() {
//		return endereco;
//	}
//
//	public void setEndereco(Endereco endereco) {
//		this.endereco = endereco;
//	}

	public EnderecoDataModel getEnderecoDataModel() {
		if (this.enderecoDataModel == null)
			this.enderecoDataModel = new EnderecoDataModel(
					this.enderecoService.getList(this.cliente));
		return enderecoDataModel;
	}

	public void setEnderecoDataModel(EnderecoDataModel enderecoDataModel) {
		this.enderecoDataModel = enderecoDataModel;
	}

	public TipoFrete getTipoFrete() {
		return tipoFrete;
	}

	public void setTipoFrete(TipoFrete tipoFrete) {
		this.tipoFrete = tipoFrete;
		setSession("tipoFrete", tipoFrete);
	}

	public Frete getFrete() {
		return frete;
	}

	public void setFrete(Frete frete) {
		this.frete = frete;
	}

}
